perm filename LISP70.MAN[L70,TES] blob sn#055281 filedate 1973-07-18 generic text, type T, neo UTF8
00100	The Lisp70 Manual.
00200	
00300	How to do a few things in Lisp70, such as Factorial using
00400	recursion, iteration.  Integer variables.
00500	
00600	Inner product of two arrays.  Inner product of two
00700	lists.
00800	
00900	Generic function inner product.
01000	
01100	Printing out an array of numbers.  Printing out a list of numbers.
01200	Printing out a list of identifiers.  Printing out a list of
01300	lists and various other things.
01400	
01500	Printing on a disk file.  Public variables.
01600	
01700	Reading from the terminal.  From a file.
01800	
01900	Dictionary read-in using dot notation.
02000	
02100	Alphabetized dictionary: use of a lexicon.
02200	
02300	Long term memory.
02400	
02500	Garbage collection.
02600	
02700	Pattern matching (paper examples).
02800	
02900	Generators -- show random number generator and lexicon-entry generator.
03000	
03100	Coroutines.  Streaming.
03200	
03300	Decision points.  Failures.  Suspends.
03400	
03500	Double arrow (backtrackable) rewrite rules.
03600	
     

00100	LISP70
00200	
00300	Lisp70 is a derivative of LISP, in the family line MLISP -> MLISP2 ->
00400	LISP70.
00500	In addition to the usual S-expression notation, like (PLUS A B),
00600	the programmer can write Algol-like notation, like A+B.
00700	There is also a pattern matching notation of particular clarity.
00800	To find the derivative of 2X with respect to X,
00900	one could call a function DERIVATIVE('(TIMES 2 X), 'X) where DERIVATIVE
01000	is defined by a collection of rules which include:
01100		(TIMES :A :V) :V -> :A
01200	The variable :A would match 2, the variable :V would match X,
01300	and the answer would be the value of :A, which is 2.
01400	
01500	LISP70 is best learned by examples.  We will start with the
01600	venerable recursive function FACTORIAL.
01700	
01800	This won't work very well for anything but nonnegative integers.
01900	It is translated by the compiler to LISP as follows:
02000	
02100	(DECLARE FACTORIAL FUNCTION (N)
02200		(COND	((EQUAL N 0) 1)
02300			(T (TIMES N (FACTORIAL (SUB1 N)))) )
02400	
02500	This in turn is translated to machine language and is stored away
02600	ready to invoke by a function call  Note that all programs
02700	are compiled; there is no interpreter.  Even when EVAL
02800	is called at run-time, the compiler is used to generate
02900	code that is executed and then discarded.
03000	This has the advantage that a program will
03100	run the same whether you are in debugging or in production.
03200	This is unlike other LISP systems, which all claim to have
03300	compatible interpreters and compilers, but don't when
03400	you read the fine print or actually try it.  (SPECIAL
03500	GLOBALVAR∞
03600	
03700	Always compiling has the disadvantage that it takes longer to
03800	get a function started executing the first time it is called,
03900	because it has to be compiled first.  To minimize these delays
04000	which are especially bothersome during debugging, LISP70
04100	only translates from the M-notation to the S-notation
04200	when a function is read in.  The final translation to
04300	machine language is deferred until the first time the function is
04400	called.  Thus, if there is an error in the first function you call,
04500	you won't have to wait for an entire compilation to find this
04600	out.
04700	
04800	Another advantage of deferring final translation is that the
04900	compiler can generate much better code when it knows
05000	about the functions that are called from any given function.
05100	Variables can be typed to help the compiler generate better code:
05200	
05300	INTEGER FUNCTION FACTORIAL (INTEGER N) =
05400		IF N=0 THEN 1
05500		ELSE N * FACTORIAL(N-1) ;
05600	
05700	In this example, the variable N is declared to be type INTEGER.
05800	If someone calls FACTORIAL(NIL), the compiler will give an error
05900	message.  If someone calls FACTORIAL(Y), and the compiler can't
06000	tell what the type of the value of Y will be at run time, it inserts
06100	a run-time check to report an error if FACTORIAL is called
06200	with a non-integer argument.
06300	The function itself is also declared integer.  This means that
06400	its result must be an integer.  Any caller can be confident that
06500	an integer will be returned.  None of the horrible "boxing" and
06600	"interning" and "FIXNUMing" that happens to integers in LISP
06700	will happen to your integers if you declare your INTEGER
06800	variables and INTEGER functions to be type INTEGER.
06900	
07000	
07100	The code generated for the function FACTORIAL itself is
07200	better than in the first version, because the functions
07300	EQUAL (=), TIMES (*), and DIFFERENCE (-) don't have to check that
07400	their arguments are numbers; in fact, they compile integer
07500	arithmetic inline in the second version.  Furthermore, the
07600	recursive call on FACTORIAL does not have to check to
07700	see that N-1 is an integer.
07800	
07900	If FACTORIAL is passed a negative argument, it will go in an
08000	non-terminating loop.  After a while,
08100	either a push-down stack will overflow or the TIMES function
08200	will generate a product that exceeds the machine precision.
08300	In either case, the program will pause and tell you one of the
08400	following things:
08500	DEEP RECURSION IN FACTORIAL(N= -7642).  CONTINUEλY OR N)
08600	(-14 * -5872486) EXCEEDS MACHINE CAPACITY.  TRUNCATEλY OR N)
08700	If you answer Y, the program will continue and you will not
08800	be asked again about the same difficulty.  In the case of
08900	a deep recursion, the stacks are enlarged.  If it needs to
09000	be enlarged again, you will be not be told,
09100	but if memory space is completely exhausted, you will be told
09200	about that instead.
09300	
09400	If you would rather not receive such error messages, or would
09500	rather receive more of them, read the section on ERRORS AT RUNTIME.
09600	
09700	If you answer N instead of Y to the above questions, you will be
09800	given an opportunity to debug your program.  Right now, the debugger
09900	is not as powerful as some, but you can find out how you got
10000	where you are, interrogate variables, set breakpoints at the
10100	beginnings and ends of functions, and in fact evaluate any
10200	expression (in either M-notation or S-notation).
10300	
10400	One way to avoid deep recursions is to use
10500	what is loosely known in computerese as iteration, i.e., loops.
10600	This won't prevent excessive products, but it will prevent stack
10700	overflows and sometimes speed up a program.  LISP70 is full of
10800	iteration facilities; probably there are more than you need, but we
10900	will go to great lengths to avoid GO-TO's (which are
11000	illegal) and other confusions.
11100	
11200	INTEGER FUNCTION FACTORIAL (INTEGER N) =
11300		BEGIN
11400		INTEGER FAC ← 1 ;
11500		FOR INTEGER I ← 1 TO N DO FAC ← FAC * I ;
11600		RETURN(FAC) ;
11700		END ;
11800	
11810	BEGIN...END is like a LISP PROG or an Algol block.  There can be
11820	declarations local to the block.  These declarations can bind
11830	variables to initial values and type the variables.  In the
11840	example, the variable FAC is declared local to the block,
11850	obscuring any meaning the name FAC had outside the
11860	block.  The variable FAC is typed as an INTEGER, and initiallized to 1.
11870	If no initiallization were mentioned, it would have
11880	been initiallized to zero.
11890	
11900	After the declaration of FAC
11910	comes a FOR statement as in Algol or MLISP.  Notice that
11920	I is declared INTEGER; this makes it local to the FOR statement.
11930	If N=0, the loop is executed zero times.  What happens if
11940	N is greater than zero should be obvious.
11950